﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;

namespace Framework.Core.Helper
{
	/// <summary>
	/// 使用IHttpClientFactory实现 HTTP远程请求 封装
	/// </summary>
	public class HttpHelper : ITransientDependency
	{
		private IHttpClientFactory _HttpClientFactory { get; }

		public HttpHelper(IHttpClientFactory httpClientFactory)
		{
			_HttpClientFactory = httpClientFactory;
		}

		/// <summary>
		/// 发起POST同步请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="postData"></param>
		/// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
		/// <param name="headers">填充消息头</param>
		/// <returns></returns>
		public string HttpPost(string url, string postData = null, string contentType = "application/json", int timeOut = 30, Dictionary<string, string> headers = null)
		{
			HttpClient _HttpClient = _HttpClientFactory.CreateClient();

			postData = postData ?? "";
			if (headers != null)
			{
				foreach (var header in headers)
					_HttpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
			}
			using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
			{
				if (contentType != null)
					httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);

				HttpResponseMessage response = _HttpClient.PostAsync(url, httpContent).Result;
				return response.Content.ReadAsStringAsync().Result;
			}
		}

		/// <summary>
		/// 发起POST异步请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="postData"></param>
		/// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
		/// <param name="headers">填充消息头</param>
		/// <returns></returns>
		public async Task<string> HttpPostAsync(string url, string postData = null, string contentType = "application/json", int timeOut = 30, Dictionary<string, string> headers = null)
		{
			HttpClient _HttpClient = _HttpClientFactory.CreateClient();
			postData = postData ?? "";
			_HttpClient.Timeout = new TimeSpan(0, 0, timeOut);
			if (headers != null)
			{
				foreach (var header in headers)
					_HttpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
			}

			using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
			{
				if (contentType != null)
					httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);

				HttpResponseMessage response = await _HttpClient.PostAsync(url, httpContent);
				return await response.Content.ReadAsStringAsync();
			}
		}

		/// <summary>
		/// 发起GET同步请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="headers"></param>
		/// <param name="contentType"></param>
		/// <returns></returns>
		public string HttpGet(string url, string contentType = "application/json", Dictionary<string, string> headers = null)
		{
			HttpClient _HttpClient = _HttpClientFactory.CreateClient();

			if (contentType != null)
				_HttpClient.DefaultRequestHeaders.Add("ContentType", contentType);
			if (headers != null)
			{
				foreach (var header in headers)
					_HttpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
			}
			HttpResponseMessage response = _HttpClient.GetAsync(url).Result;
			return response.Content.ReadAsStringAsync().Result;
		}

		/// <summary>
		/// 发起GET异步请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="headers"></param>
		/// <param name="contentType"></param>
		/// <returns></returns>
		public async Task<string> HttpGetAsync(string url, string contentType = "application/json", Dictionary<string, string> headers = null)
		{
			HttpClient _HttpClient = _HttpClientFactory.CreateClient();

			if (contentType != null)
				_HttpClient.DefaultRequestHeaders.Add("ContentType", contentType);
			if (headers != null)
			{
				foreach (var header in headers)
					_HttpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
			}
			HttpResponseMessage response = await _HttpClient.GetAsync(url);
			return await response.Content.ReadAsStringAsync();
		}

		/// <summary>
		/// 发起POST同步请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="postData"></param>
		/// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
		/// <param name="headers">填充消息头</param>
		/// <returns></returns>
		public T HttpPost<T>(string url, string postData = null, string contentType = "application/json", int timeOut = 30, Dictionary<string, string> headers = null)
		{
			return JsonHelper.StrToObj<T>(HttpPost(url, postData, contentType, timeOut, headers));
		}

		/// <summary>
		/// 发起POST异步请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="postData"></param>
		/// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
		/// <param name="headers">填充消息头</param>
		/// <returns></returns>
		public async Task<T> HttpPostAsync<T>(string url, string postData = null, string contentType = "application/json", int timeOut = 30, Dictionary<string, string> headers = null)
		{
			var res = await HttpPostAsync(url, postData, contentType, timeOut, headers);
			return JsonHelper.StrToObj<T>(res);
		}

		/// <summary>
		/// 发起GET同步请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="headers"></param>
		/// <param name="contentType"></param>
		/// <returns></returns>
		public T HttpGet<T>(string url, string contentType = "application/json", Dictionary<string, string> headers = null)
		{
			return JsonHelper.StrToObj<T>(HttpGet(url, contentType, headers));
		}

		/// <summary>
		/// 发起GET异步请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="headers"></param>
		/// <param name="contentType"></param>
		/// <returns></returns>
		public async Task<T> HttpGetAsync<T>(string url, string contentType = "application/json", Dictionary<string, string> headers = null)
		{
			var res = await HttpGetAsync(url, contentType, headers);
			return JsonHelper.StrToObj<T>(res);
		}

		/// <summary>
		/// 一个包含文本字段和文件的form-data请求
		/// </summary>
		/// <param name="url"></param>
		/// <param name="textFieldKey"></param>
		/// <param name="textFieldValue"></param>
		/// <param name="fileStream"></param>
		/// <param name="fileName"></param>
		/// <param name="contentType"></param>
		/// <returns></returns>
		public async Task<HttpResponseMessage> SubmitFormDataAsync(string url, string textFieldKey, string textFieldValue, Stream fileStream, string fileName, string contentType)
		{
			HttpClient _HttpClient = _HttpClientFactory.CreateClient();
			using (var formData = new MultipartFormDataContent())
			{
				// 添加文本字段
				formData.Add(new StringContent(textFieldValue), textFieldKey);

				// 添加文件
				var fileContent = new StreamContent(fileStream);
				fileContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(contentType);
				formData.Add(fileContent, "file", Path.GetFileName(fileName));

				// 发送请求
				var response = await _HttpClient.PostAsync(url, formData);

				return response;
			}
		}

		/// <summary>
		/// 下载网络资源
		/// </summary>
		/// <param name="url"></param>
		/// <param name="localPath"></param>
		/// <param name="action"></param>
		/// <param name="mode"></param>
		/// <returns></returns>
		public async Task DownloadFileAsync(string url, string localPath, Action<long, long> action,FileMode mode)
		{
			HttpClient _HttpClient = _HttpClientFactory.CreateClient();

			using (HttpResponseMessage response = await _HttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
			{
				using (Stream stream = await response.Content.ReadAsStreamAsync())
				{
					using (FileStream fileStream = new FileStream(localPath, mode, FileAccess.Write, FileShare.None, 8192, true))
					{
						byte[] buffer = new byte[8192];
						int bytesRead;
						long totalBytesRead = 0;
						long totalBytes = response.Content.Headers.ContentLength ?? -1;

						while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
						{
							await fileStream.WriteAsync(buffer, 0, bytesRead);
							totalBytesRead += bytesRead;
							action?.Invoke(totalBytesRead, totalBytes);     // 返回实时的下载进度
						}
					}
				}
			}
		}

		/// <summary>
		/// 忽略所有请求证书
		/// </summary>
		public void ApproveAllCerts()
		{
			ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) =>
			{
				return true;
			};
		}
	}
}
